
import time
import redis
from crc import crc16_xmodem
from setting import CABINET_CURRENT_RFID_READER_STATUS
import logging

LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"
logging.basicConfig(level=logging.INFO, format=LOG_FORMAT)
logger = logging.getLogger(__name__)


class RfidReaderStack:

    def __init__(self) -> None:
        
        self.r = redis.Redis(host='localhost', port=6379, db=0)


    def parsing_callback_commands(self, command: bytes)->bytes: # 解析回调命令 递归函数

        logger.info("command: {}".format(command))

        if not command or command[0] != 90 or len(command) < 10:

            return command
        
        protocol_code = command[1:5]

        if not (protocol_code.hex() in ["00010210", "00011200", "000102ff"]):

            return command[1:]

        args_length =  command[5: 7]

        args_length = args_length[0]<<8|args_length[1]

        if protocol_code.hex() == "00010210" and args_length == 1: # 开启读epc标签命令

            if len(command) < 7+args_length+2:

                return command
            
            info = command[0: 7+args_length+2]

            if self.crc_verification(info):

                logger.info("开启读epc标签命令: {}".format(info.hex()))

            else:

                logger.error("CRC验证失败")

                logger.error("开启读epc标签命令: {}".format(info.hex()))

           

        elif protocol_code.hex() == "00011200" and args_length == 24: # EPC标签信息

            if len(command) < 7+args_length+2:

                return command
            
            info = command[0: 7+args_length+2]

            if self.crc_verification(info):

                logger.info("扫到的EPC标签回调: {}".format(info.hex()))

                epc_code = self.get_epc_code(info)

                if epc_code:

                    self.r.sadd("now_esp_set", epc_code)

            else:

                logger.error("CRC验证失败")

                logger.error("扫到的EPC标签回调: {}".format(info.hex()))


        elif protocol_code.hex() == "000102ff" and args_length == 1: # 停止指令回调
            # 5A 000102FF 0001 0079B1

            if len(command) < 7+args_length+2:

                return command
            
            info = command[0: 7+args_length+2]
            
            if self.crc_verification(info):

                logger.info("停止指令回调: {}".format(info.hex()))

                self.r.set(CABINET_CURRENT_RFID_READER_STATUS, '收到暂停')

            else:

                logger.error("CRC验证失败")

                logger.error("停止指令回调: {}".format(info.hex()))

        else:

            return command[1:] # 没有要处理的协议控制字则把开头5a去掉返回


        
        # return command[7+args_length+2:]
        return self.parsing_callback_commands(command[7+args_length+2:]) # 递归调用


    def crc_verification(self, command: bytes) -> bool: # crc验证

        protocol_code = command[1:5]

        args_length =  command[5: 7]

        args_length = args_length[0]<<8|args_length[1]

        args = command[7: 7+args_length]

        crc = command[-2:].hex().upper()

        logger.info("解析CRC：{}".format(crc16_xmodem(command[1:-2].hex()).upper().strip().replace(' ', '')))
        logger.info("原CRC：{}".format(crc))

        return crc16_xmodem(command[1:-2].hex()).upper().strip().replace(' ', '') == crc

        # logger.info('头：{} - protocol_code：{} - args_length：{} - args: {} - crc: {}'.format(command[0], protocol_code.hex(), args_length, args.hex(), crc.hex()))

        # logger.info("协议控制字：{}".format(protocol_code.hex()))

    
    def get_element(self):

        logger.info("*"*10 + "处理RFID读头交来的数据" + "*"*10)

        joint_info = b"" # 拼接

        self.r.delete('rfid_reader_stack')

        while True:

            _, element = self.r.blpop("rfid_reader_stack")

            hex_element = element.hex()

            logger.info("hex_element:{}".format(hex_element))

            logger.info("self.r.llen('rfid_reader_stack'): {}".format(self.r.llen('rfid_reader_stack')))

            if self.r.llen('rfid_reader_stack') == 0:

                time.sleep(0.5) # 等待一下串口上交数据

            # stack_list_length = self.r.llen('rfid_reader_stack')

            if not joint_info and hex_element[0:2] == "5a": # 如果joint_info 为空 且收到的element数据是以5a开头的

                joint_info = self.parsing_callback_commands(element)

                continue

            joint_info += element

            if joint_info[0] != 90:

                Z_index = element.find(b'Z')

                if Z_index == -1: # joint_info 没有Z 抛掉

                    joint_info = b""

                    continue
                else:

                    joint_info = element[Z_index:]


            if joint_info[0] == 90:

                joint_info = self.parsing_callback_commands(joint_info)

    def get_epc_code(self, raw_command):

        '''获取epc'''

        protocol_control_word = raw_command[1:5]

        if protocol_control_word.hex() != "00011200": # 检查协议控制字

            return None

        logger.info("protocol_control_word: {}".format(protocol_control_word.hex()))

        epc = raw_command[9:21].hex()

        return epc


if __name__=="__main__":

    RfidReaderStack().get_element()

        
